package com.zixi.ai.framework.dao.spec;

import jakarta.persistence.criteria.*;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

/**
 * @author mqiqe
 */
@Getter
public class SimpleExpression implements Criterion {
    /** 属性名 */
    private final String fieldName;
    /** 对应值 */
    private final Object value;
    /** 计算符 */
    private final Operator operator;
  
    protected SimpleExpression(String fieldName, Object value, Operator operator) {  
        this.fieldName = fieldName;  
        this.value = value;  
        this.operator = operator;  
    }

    @Override
	@SuppressWarnings({ "rawtypes", "unchecked" })  
    public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
                                 CriteriaBuilder builder) {
        Path expression;
        if(fieldName.contains(".")){  
            String[] names = StringUtils.split(fieldName, ".");  
            expression = root.get(names[0]);  
            for (int i = 1; i < names.length; i++) {  
                expression = expression.get(names[i]);  
            }  
        }else{  
            expression = root.get(fieldName);  
        }
        return switch (operator) {
            case ISEMPTY -> builder.or(builder.isNull(expression), builder.equal(builder.length(expression), 0));
            case ISNOTEMPTY ->
                    builder.and(builder.isNotNull(expression), builder.greaterThan(builder.length(expression), 0));
            case ISNULL -> builder.isNull(expression);
            case ISNOTNULL -> builder.isNotNull(expression);
            case EQ -> builder.equal(expression, value);
            case NE -> builder.notEqual(expression, value);
            case LIKE -> builder.like(expression, "%" + value + "%");
            case NLIKE -> builder.like(expression, "%" + value + "%").not();
            case LIKE_CUSTOM -> builder.like(expression, value + "");
            case LT -> builder.lessThan(expression, (Comparable) value);
            case GT -> builder.greaterThan(expression, (Comparable) value);
            case LTE -> builder.lessThanOrEqualTo(expression, (Comparable) value);
            case GTE -> builder.greaterThanOrEqualTo(expression, (Comparable) value);
            default -> null;
        };
    }  
      
}  